#ifndef MODTABLE_H_
#define MODTABLE_H_

#include "scHeader.h"
#include <QAbstractTableModel>
#include <QModelIndex>
#include "Request.h"

namespace sybilpm
{
/**
 * This is a model layer above DataTable/DataObject/DataCell dedicated for
 * use with table-like views. It is based on (currently) one "home"-table
 * but it can access and decode data fields of referenced tables for display.
 * Models request the data they need from the data model on their own, the
 * view shall not interfere.
 * Note that the update method (mapRowsSl) is triggered automatically for
 * changes of the underlying DataTable object but it is not aware of changes
 * in global parameter which are used in mapping. Example: Deadline in
 * ModTimeSlice.
 * They will listen to transId-less dataChangeSig and re-map their content.
 * They will ignore foreign dataChangeSig because - assuming their initial
 * request was correct - it won't change anything.
 */
class ModTable : public QAbstractTableModel
{
	Q_OBJECT
public:
	virtual ~ModTable();
	virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
	virtual int columnCount(const QModelIndex & parent = QModelIndex()) const;
	virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
	virtual QString data(int col, PkType pk, bool sortable = false) const;
	virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
	virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
	virtual PkType mapRow2Pk(int row) const;
	virtual PkType mapRow2Ik(int row) const;
	bool isTouched() const {return touched;}
	void clearTouched() {touched=false;}
	virtual void setTouched();
public slots:
	/**
	 * Call this slot after modifying the underlying table or
	 * any global setting used in the mapping process, e.g. the
	 * global deadline.
	 */
	virtual void mapRowsSl(unsigned long transactionId);
protected:
	struct Comparer
	{
		Comparer(ModTable * parent, int column, bool ascending) : pr(parent), col(column), asc(ascending) {}
		bool operator()(PkType a, PkType b);
		ModTable * pr;
		int col;
		bool asc;
	};
	typedef std::vector<PkType> RowMap;
	typedef std::map<int,unsigned int> ColMap;
	/**
	 * This constructor is for derived classes only because it does not call
	 * mapRows internally. (But it had to be called if you create really a
	 * ModTable object.) Reason is that you must not call a virtual function
	 * in a base class constructor - vtable not set up properly at this point
	 * in time.
	 */
	ModTable(PkType entityId, QObject * parent);
	const DataTable & dt;
	Request rq;
	bool setup;
	unsigned long transId;
	ColMap colMap;
	int nVisCells;
	RowMap rowMap;
	bool touched;
};

} // namespace sybilpm
#endif /* MODTABLE_H_ */
